package com.llu.classload;

import java.io.*;

public class MyClassLoader extends ClassLoader{

    private String root;

    /**
     * 查找指定类的字节码数据并定义为Class对象
     *
     * @param name 类的全限定名
     * @return 定义的Class对象
     * @throws ClassNotFoundException 如果找不到类的字节码数据，则抛出此异常
     */
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 加载指定类的字节码数据 ， 直接从文件查找
        byte[] classData = loadClassData(name);
        if (classData == null) {
            // 如果字节码数据为空，说明类未找到，抛出ClassNotFoundException异常
            throw new ClassNotFoundException();
        } else {
            // 使用类的字节码数据定义Class对象并返回
            return defineClass(name, classData, 0, classData.length);
        }
    }


    /**
     * 根据类名加载类数据
     *
     * @param className 类名，用于定位类文件
     * @return 返回加载的类数据，如果加载失败返回null
     *
     * 此方法根据给定的类名构建文件路径，读取对应的.class文件内容，并将其返回为字节数组
     * 主要用于动态加载类文件，以便在运行时获取类的二进制数据
     */
    private byte[] loadClassData(String className) {
        // 构建类文件的完整路径
        String fileName = root + File.separatorChar
                + className.replace('.', File.separatorChar) + ".class";
        try {
            // 打开文件输入流
            InputStream ins = new FileInputStream(fileName);
            // 创建字节输出流，用于将读取的数据组装成字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 定义读取数据的缓冲区大小
            int bufferSize = 1024;
            // 创建缓冲区
            byte[] buffer = new byte[bufferSize];
            // 定义变量存储每次读取的数据长度
            int length = 0;
            // 循环读取文件数据，直到文件末尾
            while ((length = ins.read(buffer)) != -1) {
                // 将读取的数据写入到输出流中
                baos.write(buffer, 0, length);
            }
            // 返回文件的字节数据
            return baos.toByteArray();
        } catch (IOException e) {
            // 异常处理：打印异常信息
            e.printStackTrace();
        }
        // 如果发生异常，返回null
        return null;
    }


    public String getRoot() {
        return root;
    }

    public void setRoot(String root) {
        this.root = root;
    }

    public static void main(String[] args)  {

        MyClassLoader classLoader = new MyClassLoader();
        classLoader.setRoot("E:\\code\\Java代码审计系统学习\\CodeReviewStudy\\day15-classLoadAndReflcetAndSerial\\target\\classes");

        Class<?> testClass = null;
        try {
            testClass = classLoader.loadClass("com.llu.classload.Test2");
            Object object = testClass.newInstance();
            System.out.println(object.getClass().getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
